package com.yc.thread;

//生产者 消费者
public class Test17_productConsumer {
    public static void main(String[] args) {
        AppleBox ab = new AppleBox();

        Producer p  = new Producer(ab);
        Producer p2 = new Producer(ab); //不管有多少Producer，他们操作同一个AppleBox
        Producer p3 = new Producer(ab);

        Consumer c1 = new Consumer(ab);
        ///////以上是任务，要用线程绑定/////////////////////////////////////
        new Thread(p).start();
        new Thread(p2).start();
        new Thread(p3).start();

        new Thread(c1).start();
    }
}
class Apple{
    String id;

    public Apple(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "Apple:" +
                "id=" + id +
                '}';
    }
}
//消息中间缓存区：存消息的  有界阻塞队列，但在这里是一个数组
class  AppleBox{
    Apple[] apples = new Apple[5];
    int index=0;
    //生产后存消息的方法
    public  synchronized void deposite(Apple apple){   //synchronized解决苹果丢失问题
        //判断容器数组满了没有，让线程睡1s
        while (index==apples.length) { //while ：下标越界
//            try {
//                Thread.sleep(1000);
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
            try {
                this.wait(); //解决释放锁，不然会死锁
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        this.notifyAll();
        apples[index]=apple;
        index++;

    }
    //消费消息
    public synchronized Apple withdraw(){
        //判断数组是否空
        while (index==0) {
//            try {
//                Thread.sleep(1000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        this.notifyAll();  //唤醒所有的生产者
        index--;
        return  apples[index];

    }
}

class Producer implements  Runnable{
    AppleBox ab=null;//生产完的消息要存放到 appBox

    Producer(AppleBox ab) {
        this.ab=ab;
    }
    @Override
    public void run() {
        for (int i=0;i<5;i++){
            Apple a = new Apple(Thread.currentThread().getName()+"牌"+i);
            ab.deposite(a);//存消息
            System.out.println(Thread.currentThread().getName()+"生产了 "+a);//a.toString()
            try {
                Thread.sleep((long) (Math.random()*1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


class Consumer implements  Runnable{
    AppleBox ab=null;//生产完的消息要存放到 appBox

    Consumer(AppleBox ab) {
        this.ab=ab;
    }
    @Override
    public void run() {
        //从applebox中去消息出来消费
       while(ab.index>0) {
            Apple a = ab.withdraw();//取出消息出来消费
            System.out.println(Thread.currentThread().getName()+"消费了"+a);//a.toString()
            try {
                Thread.sleep((long) (Math.random()*1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
